在音视频蓬勃发展的今天、加之传统影像和AI的遭遇,在包含手机在内的终端产品上、OpenGL ES技术不可忽缺,习之~
1、背景
只记得有一次面试,面试官提到一个问题,既然你对OpenGL ES有一定的了解,那么可否写一个纹理镜像呢,但是脑子有点懵,对OpenGL ES了解的很初级,并没有回答出来,此篇文章用以记录;
2、基础知识
2.1、坐标系
2.2、GLSL基础语法
2.2.1、变量及变量类型
变量类别 | 变量类型 | 描述 |
---|---|---|
空 | void | 用于无返回值的函数或空的参数列表 |
标量 | float, int, bool | 浮点型,整型,布尔型的标量数据类型 |
浮点型向量 | float, vec2, vec3, vec4 | 包含1,2,3,4个元素的浮点型向量 |
整数型向量 | int, ivec2, ivec3, ivec4 | 包含1,2,3,4个元素的整型向量 |
布尔型向量 | bool, bvec2, bvec3, bvec4 | 包含1,2,3,4个元素的布尔型向量 |
矩阵 | mat2, mat3, mat4 | 尺寸为2x2,3x3,4x4的浮点型矩阵 |
纹理句柄 | sampler2D, samplerCube | 表示2D,立方体纹理的句柄 |
除上述之外,着色器中还可以将它们构成数组或结构体,以实现更复杂的数据类型。
2.2.2、限定符
限定符 | 描述 |
---|---|
< none: default > | 局部可读写变量,或者函数的参数 |
const | 编译时常量,或只读的函数参数 |
attribute | 由应用程序传输给顶点着色器的逐顶点的数据 |
uniform | 在图元处理过程中其值保持不变,由应用程序传输给着色器 |
varying | 由顶点着色器传输给片段着色器中的插值数据 |
更多语法知识,详见GLSL 详解(基础篇))
2.3、OpenGL ES加载纹理
关于OpenGL ES如果加载纹理,本文不再赘述,如果需要,自行Google
3、关键步骤
接下来主要描述,在OpenGL ES加载纹理的基础上,如何显示镜像纹理;
首先,先将顶点着色器和图元着色器的代码贴上
1
2
3
4
5
6
7
8
9
10
11
attribute vec4 vPosition;
attribute vec2 vCoordinate;
uniform mat4 vMatrix;
varying vec2 aCoordinate;
void main(){
gl_Position=vMatrix*vPosition;
aCoordinate=vCoordinate;
}1
2
3
4
5
6
7
8
9
10
11
12
13
precision mediump float;
uniform sampler2D vTexture;
varying vec2 aCoordinate;
void main(){
vec4 nColor=texture2D(vTexture, aCoordinate);
float c=nColor.r*0.299f + nColor.g*0.587f + nColor.b*0.114f;
gl_FragColor=vec4(c,c,c,nColor.a);
}分析镜像纹理的绘制流程
首先,在绘制单张纹理的时候,我们会传入四个顶点坐标,四个纹理采样点坐标、分别对应如下四个位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// 顶点坐标
private static final float[] mVertex = {
-1.0f, 1.0f,
-1.0f, -1.0f,
1.0f, 1.0f,
1.0f, -1.0f
};
// 纹理采样坐标
private static final float[] mTextureCoord = {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
};
按照这样的流程,如果要绘制成镜像纹理,我们就需要绘制如下几个点,来完成对称效果:
1 | private static final float[] mVertex = { |
关于顶点坐标的绘制就不解释了,比较简单,这块主要由一个关键的概念需要理解,就是GLSL的texture2D的采样率,我们就可以实现如下效果了;